package fetcher

import (
	"bufio"
	"errors"
	"fmt"
	"golang.org/x/net/html/charset"
	"golang.org/x/text/encoding"
	"golang.org/x/text/encoding/unicode"
	"io"
	"io/ioutil"
	"my-crawler/concurrence/engine"
	"net/http"
	"strings"
)

type GetReq struct {
}

func (r *GetReq) Request(ReqData engine.ReqData) ([]byte, error) {
	<-ReqData.Rate
	data := ReqData.Payload
	header := ReqData.Header
	client := http.Client{}
	var url string
	if ReqData.Url == "" {
		panic("No Request Url！")
	}
	//如果没有拼接过则拼接url
	url = ReqData.Url
	if !strings.Contains(ReqData.Url, "?") {
		url += "?"
		for k, v := range data {
			url += k + "=" + v + "&"
		}
	}
	fmt.Println("url", url)
	req, err := http.NewRequest(
		http.MethodGet,
		url,
		strings.NewReader(""))

	//添加header
	if ct, ok := header["Content-Type"]; ok {
		req.Header.Add("Content-Type", ct)
	}
	if ck, ok := header["Cookie"]; ok {
		req.Header.Add("cookie", ck)
	}
	if ug, ok := header["User-Agent"]; ok {
		req.Header.Add("User-Agent", ug)
	}
	resp, err := client.Do(req)

	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	//验证请求是否成功
	if resp.StatusCode != http.StatusOK {
		errorStr := fmt.Sprintf("http code: %d", resp.StatusCode)
		return nil, errors.New(errorStr)
	}
	/*
			预防乱码 (判断原网页是什么字符集，然后再通过x/text库转换成uft8的body)
			需要注意的是 不能重复使用resp.Body，因为io.Reader的读指针已经到末尾会返回空。
			所以我们要在判断字符集的同时，把原始Reader返回
		**  可选代码（因为不建议这么做 可以在爬虫前判断是否需要转字符集，
			然后确定原始字符集直接进行转义，避免读取两次Reader——网页本身字节很多 占用内存）
		**
	*/
	/*encode, reader := getCharSet(resp.Body)
	utf8Reader := transform.NewReader(reader,encode.NewDecoder())
	all, _ := ioutil.ReadAll(utf8Reader)*/
	all, _ := ioutil.ReadAll(resp.Body)
	return all, nil
}

// x/net库可以根据前1024个字符串判断字符集
func getCharSet(r io.Reader) (encoding.Encoding, io.Reader) {
	//这里不能直接读取resp.body
	r2 := bufio.NewReader(r)
	newReader, err := r2.Peek(1024)
	if err != nil {
		return unicode.UTF8, r2 //默认返回一个 就不panic了
	}
	encode, _, _ := charset.DetermineEncoding(newReader, "")
	return encode, r2
}
